﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NClass.Core;

namespace AnalyticsEngine.ClonesDetection
{
	public class DiagrammPartInfo
	{
		private byte m_range = 2;
		private TypeBase[] m_entities;
		private RelationshipType[][] m_relationshipMatrix;
		private bool m_isCoupled = false;

		public DiagrammPartInfo(List<TypeBase> types, Model m)
		{
			Range = (byte)types.Count;
			Entities = new TypeBase[Range];
			for (byte i = 0; i < Range; ++i)
			{
				Entities[i] = types[i];
			}

			InitRelationshipsMatrix(m);
			InitIsCoupledFlag();
		}

		private void InitRelationshipsMatrix(Model m)
		{
			RelationshipMatrix = new RelationshipType[Range][];
			for (byte i = 0; i < Range; ++i)
			{
				RelationshipMatrix[i] = new RelationshipType[Range];
				for (byte j = 0; j < Range; ++j)
				{
					RelationshipMatrix[i][j] = RelationshipType.None;
					foreach (Relationship r in m.Relationships)
					{
						if (r.First == Entities[i] && r.Second == Entities[j])
						{
							RelationshipMatrix[i][j] = r.RelationshipType;
							break;
						}
					}
				}
			}
		}

		private void InitIsCoupledFlag()
		{
			for (byte i = 0; i < Range && !IsCoupled; ++i)
			{
				IsCoupled = false;
				for (byte j = 0; j < Range; ++j)
				{
					IsCoupled |= RelationshipMatrix[i][j] != RelationshipType.None;
				}
			}
		}

		public bool IsLikeA(DiagrammPartInfo testInfo)
		{
			bool result = CanBeCompared(this, testInfo);
			if (result)
			{ 
				for (byte i = 0; i < Range && result; ++i)
				{
					for (byte j = 0; j < Range && result; ++j)
					{
						result &= RelationshipMatrix[i][j] == testInfo.RelationshipMatrix[i][j];
					}
				}
			}
			return result;
		}

		public static bool CanBeCompared(DiagrammPartInfo a, DiagrammPartInfo b)
		{
			return a.Range == b.Range && a.IsCoupled && b.IsCoupled && !a.Equals(b) && !a.Intersect(b);
		}

		public bool IsCoupled
		{
			get
			{
				return m_isCoupled;
			}
			protected set
			{
				m_isCoupled = value;
			}
		}

		public byte Range
		{
			get
			{
				return m_range;
			}
			protected set
			{
				m_range = value;
			}
		}

		public TypeBase[] Entities
		{
			get
			{
				return m_entities;
			}
			protected set
			{
				m_entities = value;
			}
		}

		public RelationshipType[][] RelationshipMatrix
		{
			get
			{
				return m_relationshipMatrix;
			}
			protected set
			{
				m_relationshipMatrix = value;
			}
		}

		public override bool Equals(object obj)
		{
			bool result = obj.GetType() == GetType();
			DiagrammPartInfo objInNativeType = (DiagrammPartInfo)obj;
			result = objInNativeType.Range == Range;
			if (result)
			{
				for (byte i = 0; i < Range && result; ++i)
				{ 
					result = Entities.Contains<TypeBase>(objInNativeType.Entities[i]);
				}
			}
			return result;
		}

		public virtual bool Intersect(DiagrammPartInfo obj)
		{
			bool result = false;
			for (byte i = 0; i < Range && !result; ++i)
			{
				result = Entities.Contains<TypeBase>(obj.Entities[i]);
			}
			return result;
		}
	}
}